package com.itlong.cloud.controller.finance;

import com.itlong.cloud.POJO.DTO.operate.OperateBalanceAccountByPageDTO;
import com.itlong.cloud.POJO.DTO.operate.WithdrawCashAndRechargeDTO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.operate.OperateBalanceAmountGetPageVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.annotation.AuthAccessRequired;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.enumerate.FileCatalogEnum;
import com.itlong.cloud.enumerate.TradeTypeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.OperateErrorCodeEnum;
import com.itlong.cloud.paymenthub.IBalanceAccountServiceClient;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 * 运营-财务平账管理控制器.
 * </desc>
 *
 * @createDate 2018/9/20
 */
@RestController
@RequestMapping("/finance")
@RefreshScope
public class OperateBalanceAccountController {

    private static final Logger LOG = LoggerFactory.getLogger(OperateBalanceAccountController.class);

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    @Autowired
    IBalanceAccountServiceClient iBalanceAccountServiceClient;
    /**
     * <desc>
     * 分页查询平账列表
     * <desc/>
     *
     * @param balanceAccountByPageDTO
     * @return
     * @author Juguang.S
     * @createDate 2018-09-20
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping(path = "/balanceAccount/getInfoByPage")
    public Object getInfoByPage(OperateBalanceAccountByPageDTO balanceAccountByPageDTO){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            balanceAccountByPageDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateBalanceAccountByPageDTO.class,request);
            Page<OperateBalanceAmountGetPageVO> page = iBalanceAccountServiceClient.getInfoByPage(balanceAccountByPageDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),page);
        }catch (Exception e){
            throw new DataAccessException("【运营-财务平账管理】获取列表失败",e);
        }
    }

    /**
     * <desc>
     * 根据ID获取备注信息
     * <desc/>
     *
     * @param changeId 查询ID
     * @return
     * @author Juguang.S
     * @createDate 2018-09-20
     */
    @ResponseBody
    @PostMapping(path = "/balanceAccount/getRemark")
    public Object getRemark(String changeId){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            changeId=request.getAttribute("changeId")==null?null:request.getAttribute("changeId").toString();
            if(StringUtils.isEmpty(changeId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String remark = iBalanceAccountServiceClient.getRemark(changeId);
            Map<String,String> returnData = new HashMap<>();
            returnData.put("remark",remark);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),returnData);
        }catch (Exception e){
            throw new DataAccessException("【运营-财务平账管理】根据ID获取备注信息失败",e);
        }
    }

    /**
     * <desc>
     * 修改备注信息
     * <desc/>
     *
     * @param changeId 查询ID
     * @return
     * @author Juguang.S
     * @createDate 2018-09-20
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping(path = "/balanceAccount/updateRemark")
    @LoggerInfo(operateDesc = LogDescConstant.BALANCE_ACCOUNT_UPDATE_REMARK_DESC)
    public Object updateRemark(String changeId,String myUserName,String remark){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            changeId=request.getAttribute("changeId")==null?null:request.getAttribute("changeId").toString();
            myUserName=request.getAttribute("myUserName")==null?null:request.getAttribute("myUserName").toString();
            remark=request.getAttribute("remark")==null?"":request.getAttribute("remark").toString();
            if(StringUtils.isEmpty(changeId) || StringUtils.isEmpty(myUserName)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iBalanceAccountServiceClient.updateRemark(changeId,myUserName,remark);
            return new MessageVO(changeId,BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【运营-财务平账管理】修改备注信息失败",e);
        }
    }

    /**
     * <desc>
     * 财务平账-保存微信提现和备付金充值记录
     * <desc/>
     *
     * @param withdrawCashAndRechargeDTO 添加信息
     * @return
     * @author Juguang.S
     * @createDate 2018-09-20
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping(path = "/balanceAccount/withdrawCashAndRecharge")
    @LoggerInfo(operateDesc = LogDescConstant.BALANCE_ACCOUNT_SAVE_WITHDRAW_RECHARGE_DESC)
    public Object save(WithdrawCashAndRechargeDTO withdrawCashAndRechargeDTO){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            withdrawCashAndRechargeDTO=HttpProtocolUtil.parseRequestParamToDTO(WithdrawCashAndRechargeDTO.class,request);
            if(withdrawCashAndRechargeDTO == null){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if(StringUtils.isEmpty(withdrawCashAndRechargeDTO.getAmount()) || StringUtils.isEmpty(withdrawCashAndRechargeDTO.getMyUserName())){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if(Double.parseDouble(withdrawCashAndRechargeDTO.getAmount())<=0){
                return new MessageVO(OperateErrorCodeEnum.TRADE_AMCOUNT_ERR.getErrorCode());
            }
            //校验微信提现金额不能大于微信商户号余额
            if(Integer.parseInt(withdrawCashAndRechargeDTO.getTradeType())== TradeTypeEnum.WECHAT_WITHDRAW_FEE.getType()){
                BigDecimal tradeAccount = new BigDecimal(withdrawCashAndRechargeDTO.getAmount());
                BigDecimal wechatMchiAccount = iBalanceAccountServiceClient.getWechatMchiAccount();
                if(wechatMchiAccount == null){
                    wechatMchiAccount = new BigDecimal("0");
                }
                if(tradeAccount.compareTo(wechatMchiAccount)>0){
                    return new MessageVO(OperateErrorCodeEnum.WECHAT_MCHI_AMCOUNT_NOT_ENOUGH_ERR.getErrorCode());
                }
            }
            String changeId = LogicIdUtil.bussinessId();
            withdrawCashAndRechargeDTO.setChangeId(changeId);
            iBalanceAccountServiceClient.save(withdrawCashAndRechargeDTO);
            return new MessageVO(changeId,BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【运营-财务平账管理】添加失败",e);
        }
    }


    /**
     * <desc>
     * 导出EXCEL文件
     * <desc/>
     *
     * @param balanceAccountByPageDTO
     * @return
     * @author Juguang.S
     * @createDate 2018-09-20
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping(path = "/balanceAccount/exportThirdPartyPayInfo")
    public Object exportThirdPartyPayInfo(OperateBalanceAccountByPageDTO balanceAccountByPageDTO){
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            balanceAccountByPageDTO=HttpProtocolUtil.parseRequestParamToDTO(OperateBalanceAccountByPageDTO.class,request);
            List<OperateBalanceAmountGetPageVO> changeInfoPOList = iBalanceAccountServiceClient.exportFile(balanceAccountByPageDTO);
            if (changeInfoPOList == null || changeInfoPOList.isEmpty()) {
                return new MessageVO(OperateErrorCodeEnum.EXPORT_DATA_EMPTY_ERR.getErrorCode());
            }
            String[] title = {"序号","第三方支付名称","交易金额","创建时间","交易类别","操作人员","业务编号","备注"};
            short rowHeight= 420;
            //创建excel工作簿
            HSSFWorkbook workbook=new HSSFWorkbook();
            //创建工作表sheet并设置简单格式
            HSSFSheet sheet=workbook.createSheet();
            sheet.setDefaultColumnWidth(16);
            //创建第一行
            HSSFRow row=sheet.createRow(0);
            row.setHeight(rowHeight);
            HSSFCell cell=null;
            //插入第一行数据的表头
            for (int i = 0; i < title.length; i++) {
                cell = row.createCell(i);
                cell.setCellValue(title[i]);
            }
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //写入数据
            for (int carIndex = 0; carIndex < changeInfoPOList.size(); carIndex++) {
                OperateBalanceAmountGetPageVO amountGetPageVO = changeInfoPOList.get(carIndex);
                int rowIndex = carIndex + 1; // 第一行已为标题行
                HSSFRow dataRow = sheet.createRow(rowIndex);
                dataRow.setHeight(rowHeight);
                HSSFCell noteCell = dataRow.createCell(0);
                noteCell.setCellValue(rowIndex);
                noteCell = dataRow.createCell(1);
                if(amountGetPageVO.getThirdPartyPayment() != null){
                    switch (amountGetPageVO.getThirdPartyPayment()){
                        case 1:
                            noteCell.setCellValue("微信支付");
                            break;
                        case 2:
                            noteCell.setCellValue("银联支付");
                            break;
                        default:
                            break;
                    }
                }else {
                    noteCell.setCellValue("");
                }
                noteCell = dataRow.createCell(2);
                noteCell.setCellValue(amountGetPageVO.getTradeAmount().toString());
                noteCell = dataRow.createCell(3);
                noteCell.setCellValue(amountGetPageVO.getCreateTime());
                noteCell = dataRow.createCell(4);
                if(amountGetPageVO.getTradeType() != null){
                    switch (amountGetPageVO.getTradeType()){
                        case 6:
                            noteCell.setCellValue("备付金充值");
                            break;
                        case 5:
                            noteCell.setCellValue("微信提现");
                            break;
                        default:
                            break;
                    }
                }else {
                    noteCell.setCellValue("");
                }
                noteCell = dataRow.createCell(5);
                noteCell.setCellValue(amountGetPageVO.getOperate());
                noteCell = dataRow.createCell(6);
                noteCell.setCellValue(amountGetPageVO.getOutOrderNum());
                noteCell = dataRow.createCell(7);
                noteCell.setCellValue(amountGetPageVO.getRemark());
            }
            String fileName = String.format("BalanceAccountInfo_%s.xls",
                    DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));
            fileName = URLEncoder.encode(fileName, "UTF-8");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            workbook.write(os);
            byte[] content = os.toByteArray();
            InputStream exportFileStream = new ByteArrayInputStream(content);
            String exportFileUrl = this.uploadFile(exportFileStream,fileName);
            if (StringUtils.isBlank(exportFileUrl)){
                return new MessageVO(OperateErrorCodeEnum.EXPORT_FILE_SAVE_ERR.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), (Object) exportFileUrl);
        }catch (Exception e){
            throw new DataAccessException("【运营-财务平账管理】导出EXCEL文件失败",e);
        }
    }

    /**
     * <desc>
     *      Ftp上传文件，返回Url.
     * </desc>
     *
     * @param inputStream 文件流
     * @param fileName 文件名称
     * @return 文件上传成功后会返回Url,否则返回空
     * @author wangzhi
     * @createDate 2018/08/22
     */
    private String uploadFile(InputStream inputStream, String fileName) throws IOException {
        String fileUrl = "";
        String fileType = StringHandlerUtil.copySubStr(fileName, fileName.lastIndexOf('.') + 1, fileName.length());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                inputStream,
                fileType,
                FILE_ACCESS_URL,
                FileCatalogEnum.EXPORT_EXCEL_ZHANG_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == false){
            return fileUrl;
        }
        fileUrl = resultMap.get("accessPath").toString();
        return fileUrl;
    }

}